﻿using NUnit.Core;
using NUnit.Core.Builders;
using NUnit.Framework;
using Rhino.Mocks;
using Selenium;
using SeleniumToolkit.Config;
using SeleniumToolkit.Core;
using NUnit.Core.Extensibility;

namespace SeleniumToolkit.NUnit
{

    [TestFixture]
    public class FixtureBuilderTests
    {

        [TearDown]
        public void TearDown()
        {
            AddinUtil.Uninstall();
        }

        [Test]
        public void When_Building_up_TestFixture_EventListener_Should_Identify_WebFixtures_Are_Present()
        {
            IExtensionHost host = CoreExtensions.Host;

            // create basic event listener and suitebuilder for installation into nunit addin
            SeleniumConfiguration config = new SeleniumConfiguration();
            SeleniumEventListener eventListener = new SeleniumEventListener(null); // create empty eventlistener
            SeleniumTestFixtureBuilder suiteBuilder = new SeleniumTestFixtureBuilder(host,config); // create suitebuilder

            // install addin
            SeleniumNUnitAddin addin = new SeleniumNUnitAddin();
            addin.Install(host, suiteBuilder, eventListener);

            // using the installed addin, test construction of fixtures
            TestAssemblyBuilder assemblyBuilder = new TestAssemblyBuilder();
            TestSuite suite = assemblyBuilder.Build("NUnit.TestAssembly.FixtureScenario.dll", true);

            // make sure event listener knows that tests are present
            Assert.IsNotNull(suite);
            Assert.IsTrue(SeleniumEventListener.WebTestsPresent, "Web tests not found.");
            
        }

        [Test]
        public void When_Fixture_Owns_Session_SeleniumFactory_Should_Only_Create_Sessions_For_Fixtures()
        {
            SuiteTester.RunAssembly("NUnit.TestAssembly.FixtureScenario.dll", new SeleniumConfiguration(), 3);
        }
    }

    public class SuiteTester
    {
        public static void RunAssembly(string assemblyName, SeleniumConfiguration config, int expectedSessions)
        {
            try
            {
                IExtensionHost host = CoreExtensions.Host;

                var factory = MockRepository.GenerateMock<ISeleniumFactoryProvider>();
                var selenium = MockRepository.GenerateMock<ISelenium>();

                // have the factory always return our mock selenium
                factory.Expect(f => f.Create(null, 0, null, null)).IgnoreArguments().Return(selenium).Repeat.Any();
                // set our expectations for start / stop
                selenium.Expect(s => s.Start()).Repeat.Times(expectedSessions);
                selenium.Expect(s => s.Stop()).Repeat.Times(expectedSessions);

                // create our components with mock participants
                SeleniumFactory.Configure(config, factory);
                var eventListener = new SeleniumEventListener(null);
                var suiteBuilder = new SeleniumTestFixtureBuilder(host,config);
                suiteBuilder.Name = (config.AddinSettings.RecylePerFixture) ? "Fixture" : "TestCase";

                // create our addin with our components and register it with the extension host
                SeleniumNUnitAddin addin = new SeleniumNUnitAddin();
                addin.Install(host, suiteBuilder, eventListener);

                // run the test through the TestSuite
                TestAssemblyBuilder assemblyBuilder = new TestAssemblyBuilder();
                TestSuite suite = assemblyBuilder.Build(assemblyName, false);

                // assert the number of times the Browser.Start() was called
                suite.Run(eventListener,TestFilter.Empty);

                selenium.VerifyAllExpectations();
            }
            catch
            {
                throw;
            }
            finally
            {
                AddinUtil.Uninstall();
            }
        }
    }
}
